package app

import (
	"common/config"
	"common/consul"
	"common/global"
	"common/initialize"
	userApi "common/proto/api"
	"context"
	"fmt"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"
	service2 "user/service"
)

func Run(ctx context.Context, ip string, port int) error {

	//1 初始化数据库管理
	//todo
	initialize.InitManager()
	//2 初始化grpc server
	server := grpc.NewServer()
	userApi.RegisterGreeterServer(server, &service2.HelloServer{})      //这里一定要注册
	userApi.RegisterUserServiceServer(server, service2.NewUserServer()) //第二个参数传结构体
	//判断端口监听情况 准备启动当前ip端口为grpc服务端
	listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port))
	if err != nil {
		zap.S().Errorf("api grpc server listen err:%v", err)
	}
	zap.S().Infof("api grpc server listen success:%s:%d", ip, port)
	//注册服务健康检查
	grpc_health_v1.RegisterHealthServer(server, health.NewServer())

	//3 初始化consul注册器 然后进行注册
	register := consul.NewConsulRegistryClient(config.Conf.Consul)
	serviceId, err := register.Register(config.Conf.Consul, ip, port)

	// 4 挂起server异步执行
	go func() {
		//4 启动grpc server(ip端口)
		err = server.Serve(listen) //这是一个阻塞操作
		if err != nil {
			zap.S().Errorf("api grpc server run Serve err:%v", err)
		}
	}()
	stop := func() {
		register.UnRegister(serviceId)
		server.Stop()
		global.Manager.Close()
		time.Sleep(3 * time.Second)
		zap.S().Info("api app do stop finally by signal")
	}
	//期望有一个优雅的启停，遇到中断 退出 终止 挂断
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGHUP)
	for {
		select {
		case <-ctx.Done():
			stop()
			//time out
			return nil
		case s := <-c:
			switch s {
			case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT:
				stop()
				zap.S().Info("api app quit")
				return nil
			case syscall.SIGHUP:
				stop()
				zap.S().Info("hang up! api app quit")
				return nil
			default:
				return nil
			}
		}
	}
}
